package cLog

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
	"time"

	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"github.com/sirupsen/logrus"
)

type (
	FileHook struct {
		Path     string            `json:"path"`
		Format   LogFormat         `json:"format"`
		Rotation FileHook_Rotation `json:"rotation"`
	}

	FileHook_Rotation struct {
		Enable  bool         `json:"enable"`
		Type    RotationType `json:"type"`
		MaxFile int64        `json:"max_file"`
		MaxSize int64        `json:"max_size"`
	}
)

func (e FileHook) GetFormat() LogFormat {
	return e.Format
}

func (e FileHook) GetColorful() bool {
	return false
}

func (e FileHook) Levels() []logrus.Level {
	return logrus.AllLevels
}

func (e FileHook) Fire(entry *logrus.Entry) error {
	var err error
	var out string
	var writer io.Writer

	out, err = format(entry, e)
	if err != nil {
		return err
	}
	out = out + "\n"

	if e.Path == "" {
		return fmt.Errorf("file is not set")
	}

	if !e.Rotation.Enable {
		writer, err = os.OpenFile(e.Path, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644)
		if err != nil {
			return err
		}
	} else {
		var rotationFormat string
		var interval time.Duration

		switch e.Rotation.Type {
		case ROTATION_TYPE_MINUTE:
			rotationFormat = rotation_formatter_minute
			interval = time.Minute * 1
		case ROTATION_TYPE_HOUR:
			rotationFormat = rotation_formatter_hour
			interval = time.Hour * 1
		case ROTATION_TYPE_DAY:
			rotationFormat = rotation_formatter_day
			interval = time.Hour * 24
		case ROTATION_TYPE_MONTH:
			rotationFormat = rotation_formatter_month
			interval = time.Hour * 24
		case ROTATION_TYPE_YEAR:
			rotationFormat = rotation_formatter_year
			interval = time.Hour * 24
		default:
			rotationFormat = rotation_formatter_hour
			interval = time.Hour * 1
		}

		if e.Rotation.MaxFile == 0 {
			e.Rotation.MaxFile = 24
		}
		if e.Rotation.MaxSize < 0 {
			e.Rotation.MaxSize = 0
		}
		ext := filepath.Ext(e.Path)
		filename := strings.TrimRight(e.Path, fmt.Sprintf(".%s", ext))
		rotationPath := fmt.Sprintf("%s.%s%s", filename, rotationFormat, ext)
		writer, err = rotatelogs.New(
			rotationPath,
			rotatelogs.WithRotationCount(uint(e.Rotation.MaxFile)),
			rotatelogs.WithRotationTime(interval),
			rotatelogs.WithRotationSize(e.Rotation.MaxSize),
		)
		if err != nil {
			return err
		}
	}

	_, _ = writer.Write([]byte(out))

	return err
}
